package com.clx.mx.xjar.core;

import com.clx.mx.xjar.common.DirConstant;
import com.clx.mx.xjar.common.EncryptUtil;
import com.clx.mx.xjar.common.FileUtil;
import org.dmg.pmml.FieldName;
import org.jpmml.evaluator.*;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class ExePmml {

    public static Integer getExeScore(Map<String, Object> map) {
        return prob2Score(exePmml(map));
    }

    //缓冲文件内容
    private static byte[] pmmlCache = null;

    //读取pmml文件
    private static byte[] readFile() {
        if (pmmlCache != null) {
            return pmmlCache;
        } else {
            synchronized (ExePmml.class) {
                if (pmmlCache != null) {
                    return pmmlCache;
                } else {
//                    String pmmlFile = DirConstant.CONF_HOME_DIR + File.separator + DirConstant.PMML_NAME_EN;
//                    byte[] bytes = FileUtil.readByte(new File(pmmlFile));

                    InputStream resourceAsStream = ExePmml.class.getClassLoader().getResourceAsStream(DirConstant.PMML_NAME_EN);
                    byte[] bytes = FileUtil.readByte(resourceAsStream);
                    byte[] decrypt = EncryptUtil.decrypt(bytes);
                    pmmlCache = decrypt;
                    return pmmlCache;
                }
            }
        }
    }

    private static Double exePmml(Map<String, Object> irismap) {
        Double res = null;
        ByteArrayInputStream bis = null;
        try {
            byte[] bytes = readFile();
            bis = new ByteArrayInputStream(bytes);
            Evaluator evaluator = new LoadingModelEvaluatorBuilder().load(bis).build();

            List<InputField> inputFields = evaluator.getInputFields();
            Map<FieldName, FieldValue> argements = new LinkedHashMap<FieldName, FieldValue>();
            for (InputField inputField : inputFields) {
                FieldName inputFieldName = inputField.getName();
                Object raeValue = irismap.get(inputFieldName.getValue());
                FieldValue inputFieldValue = inputField.prepare(raeValue);
                argements.put(inputFieldName, inputFieldValue);
            }
            Map<FieldName, ?> results = evaluator.evaluate(argements);
            List<TargetField> targetFields = evaluator.getTargetFields();

            //这里只有一条记录所以需要替换
            FieldName targetFieldName = targetFields.get(0).getName();
            Object targetFieldValue = results.get(targetFieldName);

            //提取结果
            ProbabilityDistribution f = (ProbabilityDistribution) targetFieldValue;
            res = new Double(f.getResult().toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bis != null) {
                    bis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return res;
    }

    private static Integer prob2Score(Double prob) {
        Integer res = 0;
        if (prob != null) {
            try {
                Double basePoint = 600.0;
                Double PDO = 50.0;
                double y = Math.log(prob / (1 - prob));
                //用到公式log2N=logeN/loge2；
                double score = basePoint + PDO / (Math.log(0 - y) / Math.log(2));
                Long value = Math.round(score);
                if (value > DirConstant.SCORE) {
                    res = 1;
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return res;
    }
}
